package server

import (
	"3-19yk/common/models/es"
	"3-19yk/common/models/mysql"
	"3-19yk/common/proto/user"
	"bytes"
	"context"
	"encoding/json"
	"fmt"
	"github.com/elastic/go-elasticsearch/v7/esapi"
	"log"
	"strconv"
	"sync"
)

func EsSync(req *user.EsSyncReq) (*user.EsSyncResp, error) {
	var (
		wg   sync.WaitGroup
		list []*mysql.Scenic
	)
	mysql.DB.Debug().Find(&list)
	for _, scenic := range list {
		wg.Add(1)

		go func(scenic *mysql.Scenic) {
			defer wg.Done()

			// Build the request body.
			data, err := json.Marshal(scenic)
			if err != nil {
				log.Fatalf("Error marshaling document: %s", err)
			}

			// Set up the request object.
			req := esapi.IndexRequest{
				Index:      "scenic",
				DocumentID: strconv.Itoa(int(scenic.ID)),
				Body:       bytes.NewReader(data),
				Refresh:    "true",
			}

			// Perform the request with the client.
			res, err := req.Do(context.Background(), es.Es)
			if err != nil {
				log.Fatalf("Error getting response: %s", err)
			}
			defer res.Body.Close()

		}(scenic)
	}
	wg.Wait()
	return &user.EsSyncResp{Success: "同步成功"}, nil
}

func EsSear(req *user.EsSearReq) (*user.EsSearResp, error) {
	var buf bytes.Buffer
	var query map[string]interface{}
	if req.FormName != "" {
		query = map[string]interface{}{
			"query": map[string]interface{}{
				"match": map[string]interface{}{
					"ScenicName": req.FormName,
				},
			},
		}
	} else {
		query = map[string]interface{}{
			"query": map[string]interface{}{
				"match_all": map[string]interface{}{},
			},
		}
	}

	if err := json.NewEncoder(&buf).Encode(query); err != nil {
		log.Fatalf("Error encoding query: %s", err)
	}

	// Perform the search request.
	res, err := es.Es.Search(
		es.Es.Search.WithContext(context.Background()),
		es.Es.Search.WithIndex("scenic"),
		es.Es.Search.WithBody(&buf),
		es.Es.Search.WithTrackTotalHits(true),
		es.Es.Search.WithPretty(),
	)
	if err != nil {
		log.Fatalf("Error getting response: %s", err)
	}
	defer res.Body.Close()

	r := map[string]interface{}{}
	json.NewDecoder(res.Body).Decode(&r)
	var list []*user.ListScenic
	// Print the ID and document source for each hit.
	for _, hit := range r["hits"].(map[string]interface{})["hits"].([]interface{}) {
		m := hit.(map[string]interface{})["_source"].(map[string]interface{})
		list = append(list, &user.ListScenic{
			ScenicName:    m["ScenicName"].(string),
			BusinessHours: m["BusinessHours"].(string),
			ScenicPrice:   float32(m["ScenicPrice"].(float64)),
			ScenicAddress: m["ScenicAddress"].(string),
			Inter:         m["Inter"].(string),
			ScenicScore:   float32(m["ScenicScore"].(float64)),
			Num:           int64(m["Num"].(float64)),
		})
	}
	return &user.EsSearResp{
		List: list,
	}, nil
}

func ScenicShow(req *user.ScenicShowReq) (*user.ScenicShowResp, error) {
	scenic := mysql.Scenic{}
	show, err := scenic.ScenicShow(int(req.Id))
	if err != nil {
		return nil, fmt.Errorf("查询失败")
	}
	return &user.ScenicShowResp{
		ScenicName:    show.ScenicName,
		BusinessHours: show.BusinessHours,
		ScenicPrice:   float32(show.ScenicPrice),
		ScenicAddress: show.ScenicAddress,
		Inter:         show.Inter,
		ScenicScore:   float32(show.ScenicScore),
		Num:           int64(show.Num),
	}, nil
}
